#ifndef __JUDGE_H__
#define __JUDGE_H__

#include "../checkerBoard/CheckerBoard.hpp"
#include "../chess/Chess.hpp"
#include <cstddef>
#include <iostream>
#include <iterator>
#include <ostream>

/**
 * @brief 判断输赢类
 *
 */
class Judge {
private:
  CheckerBoard *checkerboard;

public:
  Judge() { checkerboard = CheckerBoard::getCheckerBoard(); }

  /**
   * @brief 判断胜负
   *
   * @param displayPositionX
   * @param displayPositionY
   * @return true
   * @return false
   */
  bool judgeWinningAndLosing(unsigned int displayPositionX,
                             unsigned int displayPositionY) {
    unsigned int x = 0;
    unsigned int y = 0;
    y = (displayPositionX - CHESS_BOARD_MIN_X) / CHESS_BOARD_SKIP_X;
    x = (displayPositionY - CHESS_BOARD_MIN_Y) / CHESS_BOARD_SKIP_Y;

    Chess *chess = checkerboard->getChessAt(x, y);

    if (judgeWinningAndLosingCross(chess) ||
        judgeWinningAndLosingDiagonal(chess)) {
      return true;
    } else {
      return false;
    }
  }

  /**
   * @brief     判断胜负(十字形)
   *
   * @param x
   * @param y
   * @return true
   * @return false
   */
  bool judgeWinningAndLosingCross(Chess *chess) {
    unsigned int chessType = chess->getChessType();
    unsigned int x = chess->getX();
    unsigned int y = chess->getY();
    unsigned int count1 = 0;
    unsigned int count2 = 0;
    bool judgeRight = true;
    bool judgeLeft = true;
    Chess *chesstemp = nullptr;

    for (int i = 1; i < 5; i++) {
      if (y + i < CHESS_BOARD_ROWS) {
        chesstemp = checkerboard->getChessAt(x, y + i);
        if ((chesstemp != NULL) && (judgeRight == true)) {
          if ((chesstemp->getChessType() == chessType)) {
            ++count1;
          } else {
            judgeRight = false;
          }
        } else {
          judgeRight = false;
        }
      }
      if (y - i >= 0) {
        chesstemp = checkerboard->getChessAt(x, y - i);
        if ((chesstemp != nullptr) && (judgeLeft == true)) {
          if ((chesstemp->getChessType() == chessType)) {
            ++count1;
          } else {
            judgeLeft = false;
          }
        } else {
          judgeLeft = false;
        }
      }
    }
    judgeRight = true;
    judgeLeft = true;
    for (int i = 1; i < 5; i++) {
      if (x + i < CHESS_BOARD_COLUMNS) {
        chesstemp = checkerboard->getChessAt(x + i, y);
        if ((chesstemp != NULL) && (judgeRight == true)) {
          if ((chesstemp->getChessType() == chessType)) {
            ++count2;
          } else {
            judgeRight = false;
          }
        } else {
          judgeRight = false;
        }
      }
      if (x - i >= 0) {
        chesstemp = checkerboard->getChessAt(x - i, y);
        if ((chesstemp != nullptr) && (judgeLeft == true)) {
          if ((chesstemp->getChessType() == chessType)) {
            ++count2;
          } else {
            judgeLeft = false;
          }
        } else {
          judgeLeft = false;
        }
      }
    }

    if ((count1 == 4) || (count2 == 4)) {
      return true;
    } else {
      return false;
    }
  }

  /**
   * @brief     判断胜负(对角线)
   *
   * @param x
   * @param y
   * @return true
   * @return false
   */
  bool judgeWinningAndLosingDiagonal(Chess *chess) {
    unsigned int chessType = chess->getChessType();
    unsigned int x = chess->getX();
    unsigned int y = chess->getY();
    unsigned int count1 = 0;
    unsigned int count2 = 0;
    bool judgeRight = true;
    bool judgeLeft = true;
    Chess *chesstemp = nullptr;

    for (int i = 1; i < 5; i++) {
      if ((x + i < CHESS_BOARD_COLUMNS) && (y + i < CHESS_BOARD_ROWS)) {
        chesstemp = checkerboard->getChessAt(x + i, y + i);
        if ((chesstemp != NULL) && (judgeRight == true)) {
          if ((chesstemp->getChessType() == chessType)) {
            ++count1;
          } else {
            judgeRight = false;
          }
        } else {
          judgeRight = false;
        }
      }
      if ((x - i >= 0) && (y - i >= 0)) {
        chesstemp = checkerboard->getChessAt(x - i, y - i);
        if ((chesstemp != nullptr) && (judgeLeft == true)) {
          if ((chesstemp->getChessType() == chessType)) {
            ++count1;
          } else {
            judgeLeft = false;
          }
        } else {
          judgeLeft = false;
        }
      }
    }
    judgeRight = true;
    judgeLeft = true;
    for (int i = 1; i < 5; i++) {
      if ((x + i < CHESS_BOARD_COLUMNS) && (y - i >= 0)) {
        chesstemp = checkerboard->getChessAt(x + i, y - i);
        if ((chesstemp != NULL) && (judgeRight == true)) {
          if ((chesstemp->getChessType() == chessType)) {
            ++count2;
          } else {
            judgeRight = false;
          }
        } else {
          judgeRight = false;
        }
      }
      if ((x - i >= 0) && (y + i < CHESS_BOARD_ROWS)) {
        chesstemp = checkerboard->getChessAt(x - i, y + i);
        if ((chesstemp != nullptr) && (judgeLeft == true)) {
          if ((chesstemp->getChessType() == chessType)) {
            ++count2;
          } else {
            judgeLeft = false;
          }
        } else {
          judgeLeft = false;
        }
      }
    }
    if ((count1 == 4) || (count2 == 4)) {
      return true;
    } else {
      return false;
    }
  }
};

#endif // __JUDGE_H__